use std::sync::{Arc, Mutex};

use serde::{Deserialize, Serialize};

use crate::{
    database::DataSource,
    datasource::{DataSourceProvider, GetDataSourceOptions},
    modeling::system_meta_database,
};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Context {
    default_ds: Option<DataSource>,
}

#[async_trait::async_trait]
impl DataSourceProvider for Context {
    async fn get_datasource(&self, options: GetDataSourceOptions) -> anyhow::Result<DataSource> {
        // TODO 以后扩展，支持动态选择数据源， 例如分库
        if let Some(default_res) = &self.default_ds {
            Ok(default_res.clone())
        } else {
            return system_meta_database();
        }
    }
    async fn get_datasource_id(&self, options: GetDataSourceOptions) -> anyhow::Result<u32> {
        // TODO 以后扩展，支持动态选择数据源， 例如分库
        Ok(0)
    }

    async fn set_default_datasource(&mut self, default_ds: DataSource) -> anyhow::Result<()> {
        self.default_ds = Some(default_ds);
        Ok(())
    }
}

#[async_trait::async_trait]
impl DataSourceProvider for Arc<Mutex<Context>> {
    async fn get_datasource(&self, options: GetDataSourceOptions) -> anyhow::Result<DataSource> {
        // TODO 以后扩展，支持动态选择数据源， 例如分库
        if let Some(default_res) = &self
            .lock()
            .map_err(|err| anyhow::anyhow!("{}", err))?
            .default_ds
        {
            Ok(default_res.clone())
        } else {
            return system_meta_database();
        }
    }
    async fn get_datasource_id(&self, options: GetDataSourceOptions) -> anyhow::Result<u32> {
        // TODO 以后扩展，支持动态选择数据源， 例如分库
        Ok(0)
    }

    async fn set_default_datasource(&mut self, default_ds: DataSource) -> anyhow::Result<()> {
        self.lock()
            .map_err(|err| anyhow::anyhow!("{}", err))?
            .default_ds = Some(default_ds);
        Ok(())
    }
}

impl Default for Context {
    fn default() -> Self {
        Self { default_ds: None }
    }
}
